package com.elasticsearch.wenzi.elastic.service.impl;

import com.alibaba.fastjson.JSON;
import com.elasticsearch.wenzi.elastic.constants.EsConstant;
import com.elasticsearch.wenzi.elastic.response.SearchResponse;
import com.elasticsearch.wenzi.elastic.result.ProductEsResult;
import com.elasticsearch.wenzi.elastic.result.SearchResult;
import com.elasticsearch.wenzi.elastic.service.SearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author sanmu
 * @description
 * @Date 2021/7/17
 */
@Service
@Slf4j
public class SearchServiceImpl implements SearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Override
    public boolean saveSearch(List<ProductEsResult> list) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        for (ProductEsResult productEsResult : list) {
            IndexRequest indexRequest = new IndexRequest(EsConstant.GOOD_INDEX);
            indexRequest.id(productEsResult.getProductId().toString());
            indexRequest.source(JSON.toJSONString(productEsResult), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        return bulkResponse.hasFailures();
    }

    @Override
    public SearchResponse searchKey(SearchResult searchResult) {
        SearchResponse request=null;
        SearchRequest searchRequest=querySearch(searchResult);
        try {
            //获得返回的数据
            org.elasticsearch.action.search.SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            //返回封装数据格式
            request= querySearchResponse(response,searchResult);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return request;
    }

    private SearchResponse querySearchResponse(org.elasticsearch.action.search.SearchResponse response, SearchResult searchResult) {

        SearchResponse searchRespon = new SearchResponse();
        SearchHits hits = response.getHits();

        List<ProductEsResult> voList=new ArrayList<>();
        //获得商品所有基础信息
        if(hits.getHits() != null && hits.getHits().length>0){
            for (SearchHit hit : hits.getHits()) {
                ProductEsResult esVo = JSON.parseObject(hit.getSourceAsString(), ProductEsResult.class);
                voList.add(esVo);
            }
        }
        searchRespon.setProductEsVoList(voList);
        //获取品牌数据
        ParsedLongTerms brand_agg = response.getAggregations().get("brand_agg");
        List<SearchResponse.BrandVo> brandVoList = brand_agg.getBuckets().stream().map(item -> {
            SearchResponse.BrandVo brandVo = new SearchResponse.BrandVo();
            brandVo.setBrandId(Long.parseLong(item.getKeyAsString()));
            ParsedStringTerms brand_name_agg = item.getAggregations().get("brand_name_agg");
            brandVo.setBrandName(brand_name_agg.getBuckets().get(0).getKeyAsString());
            return brandVo;
        }).collect(Collectors.toList());
        searchRespon.setBrandVoList(brandVoList);
        //获得功效数据
        ParsedNested effect_agg = response.getAggregations().get("effect_agg");
        ParsedLongTerms e_agg = effect_agg.getAggregations().get("product_effectId_agg");
        List<SearchResponse.ResponseEffect> effectList = e_agg.getBuckets().stream().map(item -> {
            SearchResponse.ResponseEffect responseEffect = new SearchResponse.ResponseEffect();
            responseEffect.setProductEffectId(((Terms.Bucket) item).getKeyAsNumber().longValue());
            ParsedStringTerms product_effectName_agg = item.getAggregations().get("product_effectName_agg");
            responseEffect.setProductEffectName(product_effectName_agg.getBuckets().get(0).getKeyAsString());
            return responseEffect;
        }).collect(Collectors.toList());
        searchRespon.setResponseEffectList(effectList);
        //当前页码
        searchRespon.setPageNnmber(searchResult.getPageNumber());
        //总记录数
        long total = hits.getTotalHits().value;
        searchRespon.setTotal(total);
        //总页码
        searchRespon.setTotalPages((int) (total%EsConstant.PASE_SIZE==0?total/EsConstant.PASE_SIZE:(total/EsConstant.PASE_SIZE+1)));
        return  searchRespon;
    }

    private SearchRequest querySearch(SearchResult searchResult) {

        //构建搜索条件
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        //查询条件
        //根据搜索查询bool
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //按照搜索框信息查询
        if(!StringUtils.isEmpty(searchResult.getKeyWork())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("productName",searchResult.getKeyWork()));
        }
        //按照品牌ID查询
        if(searchResult.getBrandId()!=null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("brandId",searchResult.getBrandId()));
        }
        //按照二级分类进行查询
        if(searchResult.getTwoCategoryId()!=null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("twoCategoryId",searchResult.getTwoCategoryId()));
        }
        //按照价格进行筛选    1-1000   1-   -1
        if(!StringUtils.isEmpty(searchResult.getPrice())){
            RangeQueryBuilder priceRange = QueryBuilders.rangeQuery("price");
            String[] priceSplit=searchResult.getPrice().split("-");
            if(priceSplit.length ==2){
                priceRange.gte(priceSplit[0]).lte(priceSplit[1]);
            }else if(priceSplit.length ==1){
                if(searchResult.getPrice().startsWith("-")){
                    priceRange.lte(priceSplit[0]);
                }
                if (searchResult.getPrice().endsWith("-")){
                    priceRange.gte(priceSplit[0]);
                }
            }
            boolQueryBuilder.filter(priceRange);
        }
        //通过功效查询  1-2-3
        if(!StringUtils.isEmpty(searchResult.getProductEffectId())){
            String[] pro=searchResult.getProductEffectId().split("-");
            for (int i = 0; i < pro.length; i++) {
                BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
                boolQuery.must(QueryBuilders.termQuery("productEffect.productEffectId",pro[i]));
                // 扁平化处理
                NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("productEffect",boolQuery, ScoreMode.None);
                boolQueryBuilder.filter(nestedQueryBuilder);
            }

        }
        searchSourceBuilder.query(boolQueryBuilder);
        //排序	price-desc /asc      lockCnt-desc/asc
        if(!StringUtils.isEmpty(searchResult.getSort())){
            String[] stringSort=searchResult.getSort().split("-");
            SortOrder order=stringSort[1].equalsIgnoreCase("asc")? SortOrder.ASC:SortOrder.DESC;
            searchSourceBuilder.sort(stringSort[0],order);
        }
        //分页
        searchSourceBuilder.from((searchResult.getPageNumber()-1)*EsConstant.PASE_SIZE);
        searchSourceBuilder.size(EsConstant.PASE_SIZE);
        //构建聚合 （品牌，功效）
        TermsAggregationBuilder brand_agg= AggregationBuilders.terms("brand_agg");
        brand_agg.field("brandId").size(50);
        brand_agg.subAggregation(AggregationBuilders.terms("brand_name_agg").field("brandName").size(50));
        searchSourceBuilder.aggregation(brand_agg);
        NestedAggregationBuilder effect_agg = AggregationBuilders.nested("effect_agg","productEffect");
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("product_effectId_agg").field("productEffect.productEffectId").size(20);
        termsAggregationBuilder.subAggregation(AggregationBuilders.terms("product_effectName_agg").field("productEffect.productEffectName").size(20));
        effect_agg.subAggregation(termsAggregationBuilder);
        searchSourceBuilder.aggregation(effect_agg);
        SearchRequest searchRequest=new SearchRequest(new String[]{EsConstant.GOOD_INDEX},searchSourceBuilder);
        System.out.println(searchSourceBuilder.toString());
        return  searchRequest;
    }
}
